package com.huiminpay.merchant.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huiminpay.merchant.api.MerchantService;
import com.huiminpay.merchant.common.cache.domain.BusinessException;
import com.huiminpay.merchant.common.cache.domain.CommonErrorCode;
import com.huiminpay.merchant.common.cache.domain.PageVO;
import com.huiminpay.merchant.common.cache.util.PhoneUtil;
import com.huiminpay.merchant.covert.StaffConvert;
import com.huiminpay.merchant.covert.StoreConvert;
import com.huiminpay.merchant.covert.StoreStaffConvert;
import com.huiminpay.merchant.dto.MerchantDTO;
import com.huiminpay.merchant.covert.MerchantCovert;
import com.huiminpay.merchant.dto.StaffDTO;
import com.huiminpay.merchant.dto.StoreDTO;
import com.huiminpay.merchant.dto.StoreStaffDTO;
import com.huiminpay.merchant.entity.Merchant;
import com.huiminpay.merchant.entity.Staff;
import com.huiminpay.merchant.entity.Store;
import com.huiminpay.merchant.entity.StoreStaff;
import com.huiminpay.merchant.mapper.MerchantMapper;
import com.huiminpay.merchant.mapper.StaffMapper;
import com.huiminpay.merchant.mapper.StoreMapper;
import com.huiminpay.merchant.mapper.StoreStaffMapper;
import com.huiminpay.user.api.TenantService;
import com.huiminpay.user.api.dto.tenant.CreateTenantRequestDTO;
import com.huiminpay.user.api.dto.tenant.TenantDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service//dubbo服务
public class MerchantServiceImpl implements MerchantService {
    //@Resource
    @Autowired
    MerchantMapper merchantMapper;
    @Autowired
    StoreMapper storeMapper;
    @Autowired
    StaffMapper staffMapper;
    @Autowired
    StoreStaffMapper storeStaffMapper;
    @Reference
    TenantService tenantService;
//    @Override
//    public com.huiminpay.merchant.dto.MerchantDTO queryMerchantById(Long id) {
//        Merchant merchant = merchantMapper.selectById(id);
//        //将Merchant转换为MerchantDTO对象
////        MerchantDTO merchantDTO = new MerchantDTO();
////        merchantDTO.setId(merchant.getId());
////        merchantDTO.setMerchantName(merchant.getMerchantName());
////        merchantDTO.setMerchantNo(merchant.getMerchantNo());
////        merchantDTO.setMerchantAddress(merchant.getMerchantAddress());
////        后续进行完善
//        MerchantDTO merchantDTO = MerchantCovert.INSTANCE.entity2Dto(merchant);
//        return merchantDTO;
//    }
    @Override
    public MerchantDTO queryMerchantById(Long merchantId) {
        Merchant merchant = merchantMapper.selectById(merchantId);
        MerchantDTO merchantDTO = MerchantCovert.INSTANCE.entity2Dto(merchant);
        return merchantDTO;
    }
    @Override
    public MerchantDTO queryMerchantByTenantId(Long tenantId) {
        Merchant merchant = merchantMapper.selectOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantId));
        return MerchantCovert.INSTANCE.entity2Dto(merchant);
    }
    //分页查询所有门店
    @Override
    public PageVO<StoreDTO> queryStoreByPage(StoreDTO storeDTO, Integer pageNo, Integer pageSize) {
        // 创建分页
        Page<Store> page = new Page<>(pageNo, pageSize);
        // 构造查询条件
        LambdaQueryWrapper<Store> qw = new LambdaQueryWrapper<>();
        if (storeDTO != null && storeDTO.getMerchantId() != null) {
            qw.eq(Store::getMerchantId, storeDTO.getMerchantId());
        }
        // 执行查询
        IPage<Store> storeIPage = storeMapper.selectPage(page, qw);
        // entity List转DTO List
        List<StoreDTO> storeList = StoreConvert.INSTANCE.listentity2dto(storeIPage.getRecords());
        // 封装结果集
        return new PageVO<>(storeList, storeIPage.getTotal(), pageNo, pageSize);
    }

    @Override
    public Boolean queryStoreInMerchant(Long storeId, Long merchantId) {
        Integer count = storeMapper.selectCount(new LambdaQueryWrapper<Store>()
                .eq(Store::getId,storeId).eq(Store::getMerchantId, merchantId));
        return count>0;
    }

    @Override
    public PageVO<StaffDTO> queryStaffByPage(StaffDTO staffDTO, Integer pageNo, Integer pageSize) {
        // 创建分页
        Page<Staff> page = new Page<>(pageNo, pageSize);
        // 构造查询条件
        LambdaQueryWrapper<Staff> qw = new LambdaQueryWrapper<>();
        if (staffDTO != null && staffDTO.getMerchantId() != null) {
            qw.eq(Staff::getMerchantId, staffDTO.getMerchantId());
        }
        // 执行查询
        IPage<Staff> staffIPage = staffMapper.selectPage(page, qw);
        // entity List转DTO List
        List<StaffDTO> staffList = StaffConvert.INSTANCE.listentity2dto(staffIPage.getRecords());
        // 封装结果集
        return new PageVO<>(staffList, staffIPage.getTotal(), pageNo, pageSize);
    }

    @Override
    public void insertStoreStaff(StoreStaffDTO storeStaffDTO) {
        //将StoreStaffDTO转换为StoreStaff
        StoreStaff storeStaff = StoreStaffConvert.INSTANCE.dto2entity(storeStaffDTO);
        // 插入数据库
        storeStaffMapper.insert(storeStaff);
    }

    @Override
    public StaffDTO queryStaffByMerchantId(Long merchantId) {
        Staff staff = staffMapper.selectOne(new LambdaQueryWrapper<Staff>().eq(Staff::getMerchantId, merchantId));
        return StaffConvert.INSTANCE.entity2dto(staff);
    }


    //商户注册
    @Transactional(rollbackFor = Exception.class)
    @Override
    public com.huiminpay.merchant.dto.MerchantDTO createMerchant(com.huiminpay.merchant.dto.MerchantDTO merchantDTO) throws BusinessException {
        //将MerchantDTO转换为Merchant
//        Merchant merchant = new Merchant();
//        merchant.setMobile(merchantDTO.getMobile());
//        merchant.setUsername(merchantDTO.getUsername());
        //对数据做合法性校验
        // 传入对象为空
        if(merchantDTO==null){
            throw new BusinessException(CommonErrorCode.E_100109);
        }
        //手机号不能为空
        if(StringUtils.isEmpty(merchantDTO.getMobile())){
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        //手机号格式不正确
        if(!PhoneUtil.isMatches(merchantDTO.getMobile())){
            throw new BusinessException(CommonErrorCode.E_100109);
        }
        //用户名不能为空
        if(StringUtils.isEmpty(merchantDTO.getUsername())){
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        //校验手机号码是否存在
        LambdaQueryWrapper<Merchant> queryWrapper = new LambdaQueryWrapper<Merchant>();
        queryWrapper.eq(Merchant::getMobile, merchantDTO.getMobile());
        Integer count = merchantMapper.selectCount(queryWrapper);
        if(count>0){
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        //2.调用SaaS接口 添加 租户并绑定和门店 员工 商户之间的关系
        /**
         1、手机号
         2、账号
         3、密码
         4、租户类型：huimin-merchant
         5、默认套餐：huimin-merchant
         6、租户名称，同账号名
         */
        CreateTenantRequestDTO requestDTO = new CreateTenantRequestDTO();
        requestDTO.setMobile(merchantDTO.getMobile());//手机号
        requestDTO.setUsername(merchantDTO.getUsername());//账号
        requestDTO.setPassword(merchantDTO.getPassword());//密码
        requestDTO.setTenantTypeCode("huimin-merchant");//租户类型：huimin-merchant
        //设置租户套餐为初始化套餐餐  套餐:根据套餐进行分配权限
        requestDTO.setBundleCode("huimin-merchant");//默认套餐：huimin-merchant
        requestDTO.setName(merchantDTO.getUsername());//租户名称，同账号名
        //如果租户在SaaS已经存在，SaaS直接 返回此租户的信息，否则进行添加
        TenantDTO tenantAndAccount = tenantService.createTenantAndAccount(requestDTO);
        if(tenantAndAccount==null || tenantAndAccount.getId()==null){
            throw new BusinessException(CommonErrorCode.E_200012);
        }
        //租户的id
        Long tenantId = tenantAndAccount.getId();
        //租户id在商户表唯一,租户和商户是一一对应的,商户就是在saas中的租户
        //根据租户id从商户表查询，如果存在记录则不允许添加商户
        Integer count1 = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantId));
        if(count1>0){
            throw new BusinessException(CommonErrorCode.E_200017);
        }


        Merchant merchant = MerchantCovert.INSTANCE.dto2Entity(merchantDTO);
        //将租户和商户绑定
        merchant.setTenantId(tenantAndAccount.getId());
        merchant.setAuditStatus("0");//0-未申请,1-已申请待审核,2-审核通过,3-审核拒绝
        merchantMapper.insert(merchant);
        //添加门店
        StoreDTO storeDTO = new StoreDTO();
        storeDTO.setMerchantId(merchant.getId());
        storeDTO.setStoreName("根门店");
        createStore(storeDTO);
        //添加员工
        StaffDTO staffDTO = new StaffDTO();
        staffDTO.setMobile(merchantDTO.getMobile());//设置手机号
        staffDTO.setUsername(merchantDTO.getUsername());//设置用户名
        staffDTO.setStoreId(storeDTO.getId());
        staffDTO.setMerchantId(merchant.getId());
        createStaff(staffDTO);
        //为门店设置管理员
        bindStaffToStore(storeDTO.getId(),staffDTO.getId());


//        //将新增商户的编号回填给MerchantDTO
//        merchantDTO.setId(merchant.getId());
        return MerchantCovert.INSTANCE.entity2Dto(merchant);
    }
    //资质申请
    @Override
    @Transactional
    public void applyMerchant(Long merchantId, MerchantDTO merchantDTO) throws BusinessException {
        //合法性检验
        if(merchantDTO==null || merchantId==null){
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        //根据商户ID查询商户
        Merchant merchant = merchantMapper.selectById(merchantId);
        //商户不存在
        if(merchant==null){
            throw new BusinessException(CommonErrorCode.E_200002);
        }
        //将查询的商户信息和页面提交的资质信息合并
        Merchant entity = MerchantCovert.INSTANCE.dto2Entity(merchantDTO);
        entity.setId(merchantId);
        entity.setMerchantName(merchantDTO.getMerchantName());
        entity.setMobile(merchantDTO.getMobile());
        //0-未申请,1-已申请待审核,2-审核通过,3-审核拒绝
        entity.setAuditStatus("1");
        //更新商户信息
        merchantMapper.updateById(entity);

    }

   //商户下新增门店
    @Override
    public StoreDTO createStore(StoreDTO storeDTO) throws BusinessException {
        Store store = StoreConvert.INSTANCE.dto2entity(storeDTO);
        log.info("商户下新增门店"+ JSON.toJSONString(store));
        storeMapper.insert(store);
        return StoreConvert.INSTANCE.entity2dto(store);
    }
    //商户下新增员工
    @Override
    public StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException {
        //1.校验手机号格式及是否存在
        String mobile = staffDTO.getMobile();
        if(StringUtils.isBlank(mobile)){
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        //根据商户id和手机号校验唯一性
        if(isExistStaffByMobile(mobile, staffDTO.getMerchantId())){
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        //2.校验用户名是否为空
        String username = staffDTO.getUsername();
        if(StringUtils.isBlank(username)){
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        //根据商户id和账号校验唯一性
        if(isExistStaffByUserName(username, staffDTO.getMerchantId())){
            throw new BusinessException(CommonErrorCode.E_100114);
        }
        Staff entity = StaffConvert.INSTANCE.dto2entity(staffDTO);
        log.info("商户下新增员工");
        staffMapper.insert(entity);
        return StaffConvert.INSTANCE.entity2dto(entity);
    }

    //根据手机号判断员工是否已在指定商户存在
    private boolean isExistStaffByMobile(String mobile, Long merchantId) {
        LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<Staff>();
        lambdaQueryWrapper.eq(Staff::getMobile, mobile).eq(Staff::getMerchantId, merchantId);
        int count = staffMapper.selectCount(lambdaQueryWrapper);
        return count > 0;
    }

   //根据账号判断员工是否已在指定商户存在
    private boolean isExistStaffByUserName(String userName, Long merchantId) {
        LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<Staff>();
        lambdaQueryWrapper.eq(Staff::getUsername, userName).eq(Staff::getMerchantId,merchantId);
        int count = staffMapper.selectCount(lambdaQueryWrapper);
        return count > 0;
    }
    //为门店设置管理员
    @Override
    public void bindStaffToStore(Long storeId, Long staffId) throws BusinessException {
        StoreStaff storeStaff = new StoreStaff();
        storeStaff.setStaffId(staffId);
        storeStaff.setStoreId(storeId);
        storeStaffMapper.insert(storeStaff);
    }


}
